/*------------------------------------------------------------------------- 
* 版权所有：北京光宇在线科技有限责任公司
* 作者：朱宏达
* 联系方式：zhuhongda@gyyx.cn
* 创建时间：  2014年10月10日 下午8:34:40 
* 版本号：v1.0 
* 本类主要用途描述：
* xxxxxxxxxxxxxxxxxxxxxx
-------------------------------------------------------------------------*/

package cn.gyyx.tools.sign.service;

import cn.gyyx.tools.sign.beans.ExtResult;
import net.aking.base.TwoTuple;


import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.util.*;

public class SignService extends ServiceBase {

    public ExtResult<String> signUrl(String originUrl, String signKey,long timestamp) {
        ExtResult<String> result = new ExtResult<String>();
        URI uri = null;
        try {
            uri = new URI(originUrl);
        } catch (URISyntaxException ex) {
            result.setMessage("传入的Url不合法!");
            return result;
        }

        //获取Uri的NameValueCollection集合
        String queryString = uri.getQuery();
        List<TwoTuple<String, String>> queryList;
        try {
            queryList = getQueryCol(queryString);
        } catch (Exception ex) {
            result.setMessage("获取Uri的NameValueCollection集合," + ex.getMessage());
            return result;
        }

        //将Unix时间戳加入到集合中 key:timestamp

        TwoTuple<String, String> tuple = new TwoTuple<String, String>("timestamp", String.valueOf(timestamp));
        queryList.add(tuple);

        //筛选掉sign和sign_type
        filtSignItem(queryList);

        Collections.sort(queryList,new Comparator<TwoTuple<String, String>>() {
            @Override
            public int compare(TwoTuple<String, String> o1, TwoTuple<String, String> o2) {
                return o1.first.compareTo(o2.first);
            }
        });

        //将筛选后的集合重新拼接组成url
        String newQuery = spliceQuery(queryList);

        //将url和key拼接然后获取MD5加密后的值
        String md5Str =uri.getPath()+"?"+ newQuery + signKey;
        String sign = MD5.md5Digest(md5Str);

        //将sign值添加到集合中
        tuple = new TwoTuple<String, String>("sign", sign);
        queryList.add(tuple);

        //sign_type添加到集合中
        tuple = new TwoTuple<String, String>("sign_type", "MD5");
        queryList.add(tuple);

        //拼接Url
        try {
            newQuery = spliceQueryEnCode(queryList);
        } catch (Exception ex) {
            result.setMessage("encode 连接发生异常," + ex.getMessage());
            return result;
        }
        String newUrl = "http://" + uri.getHost() + uri.getPath() + "?" + newQuery;

        result.setIsSuccess(true);
        result.setData(newUrl);
        return result;
    }

    /**
     * 粘合Query
     *
     * @param queryList
     * @return
     */
    private String spliceQuery(List<TwoTuple<String, String>> queryList) {
        String newQuery = "";
        for (TwoTuple<String, String> item : queryList) {
            newQuery += item.first + "=" + item.second + "&";
        }
        newQuery = newQuery.substring(0, newQuery.length() - 1);
        return newQuery;
    }

    private String spliceQueryEnCode(List<TwoTuple<String, String>> queryList) throws UnsupportedEncodingException {
        String newQuery = "";
        for (TwoTuple<String, String> item : queryList) {
            newQuery += item.first + "=" + URLEncoder.encode(item.second, "UTF-8") + "&";
        }
        newQuery = newQuery.substring(0, newQuery.length() - 1);
        return newQuery;
    }

    /**
     * 将查询参数分割并将其加入到集合中
     *
     * @param query
     * @return
     */
    private List<TwoTuple<String, String>> getQueryCol(String query) throws UnsupportedEncodingException {
        List<TwoTuple<String, String>> list = new ArrayList<TwoTuple<String, String>>();
        String[] queryArr = query.split("&");
        for (int i = 0; i < queryArr.length; i++) {
            String[] fragments = queryArr[i].split("=");
            TwoTuple<String, String> tuple = new TwoTuple<String, String>(fragments[0], URLDecoder.decode(fragments[1], "UTF-8"));
            list.add(tuple);
        }
        return list;
    }

    /**
     * 筛选掉列表中的sign和sign_type两项
     *
     * @param list
     */
    private void filtSignItem(List<TwoTuple<String, String>> list) {

        List<TwoTuple<String, String>> filterItems = new ArrayList<TwoTuple<String, String>>();
        for (TwoTuple<String, String> item : list) {
            if (item.first == "sign" || item.first == "sign_type") {
                filterItems.add(item);
            }
        }

        for (TwoTuple<String, String> item : filterItems) {
            list.remove(item);
        }
    }


}
